#ifndef INC_bss_H
#define INC_bss_H

#include "clam.h"
#include <stdio.h>
#include <gtk/gtk.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <strings.h>
#include <string.h>
#include "../seq/tree.h"

#define MARKER_NAME_FLAG		"Query="

#define REMIND_TODO(x) printf("##TODO %s:%d ##%s\n",__FILE__,__LINE__,x);fflush(0);

typedef enum{ALLCTG,CURCTG,ENDS} parsetype;
typedef enum{BLAST, MEGABLAST, BLAT} search_tool_types;

search_tool_types search_tool_type;
parsetype search_mode;


struct displayedFile{
  char name[MAXPATHLEN+1];
  char date[100];
  off_t size;
};


typedef struct ctgTotalsParm{
   int contig;
   int cst;
   int cloneHits;
   int order;
} CTG_HIT_DATA;

struct ctgsHitlistType{
   int contig;
   int cst;    /* wmn: added for blat */
   int cloneHits;    /* wmn: added for blat */
   struct ctgsHitlistType *next;
};

typedef struct queryFilSecParm{
   int seqCtg;
   char query[255];
   long size;
   int hits;
   int bestCtg;
   int numCtgsHit;
   int hitsBestCtg;
   struct ctgsHitlistType *ctgsHitlist;
   int order;
} QUERY_HIT_DATA;

typedef struct seq_data{
   char name[100];
   char name_org[200];
   int cidx;    // clone, if any,  in fpc which the seq is associated to
   int len;
   int munged;
   int seqctg;   
 
} SEQ_DATA;



typedef struct bss_filter
{
    char* type;
    char* search;
    char* results;
} BSS_FILTER;

typedef struct bss_instance
{
    /* these hold information persisted in the .bss file */

    char bssfile[MAXPATHLEN];       /* bss file - full path */
    gboolean split;                 /* was the search split by ctg */
    int split_ctg;                  /* which split ctg are we dealing with */
    search_tool_types program;      /* BLAT, etc. */
    char cutoff_str[100];           /* evalue */
    int blat_score;                 /* blat cutoff */
    char xtraParm[100];             /* additional search params */
    Array bss_hits;                 /* hits from the search */
    Array bss_queryhits;            /* hits collected per query (query table contents) */
    Array bss_ctghits;              /* hits collected per contig (contig table contents) */
    int num_initial_targets;        /* targets in the database */
    char db_dir[MAXPATHLEN];        /* directory of the database files */
    GArray* dbs;                    /* list of database files */
    char query_file[MAXPATHLEN];    /* query file selection */       
    GArray* filter_history;         /* filters newly applied to the results */
    GArray* old_filter_history;     /* filters applied earlier, hence not undoable */

    /* these just pass information during the initial search */
    int num_initial_queries;        /* queries in the original fasta file */
    char db_suffix[50];             /* suffix chosen in the database file select */
    char query_suffix[50];          /* suffix chosen in the query file select */
    char query_dir[MAXPATHLEN];     /* directory of the query files */
    char db_file[MAXPATHLEN];       /* db file selection */
    char bss_subdir[MAXPATHLEN];    /* subdirectory of BSS_results */
    GArray* queries;                /* list of query files */
    int total_hits;                 /* total hits in the blast/blat file */
    int retained_hits;              /* number of hits which hit a clone in a contig */

    int matched_clone;              /* whether we've matched a target to a clone */
    int prefix_len;                 /* if we did match, what the prefix len was found to be */
    int suffix_len;                 /* likewise the suffix */
    int seqs_matched;            /* num of target seqs which could be matched to a clone */

    parsetype batch_search_type;   /* batch mode params */
    int batch_ctg;
    int batch_fromend;
} BSS_INST;
extern struct bss_instance g_bsi;  // holds the data parsed from the currently-displayed bss file 
                                    // a non-global instance is used for writing new bss files

extern GtkWidget *gexGraph2Widget(Graph);
extern GtkWidget *gexGraphHbox(Graph);

#define BSS_NUMTYPES 23
typedef enum bss_datatype { 
                    BSS_BES, 
                    BSS_SEQCTG, /* Either parsed from name.N, name.ContigN, or just
                                    the order of the seq in its file */
                    BSS_CTG,
                    BSS_LR,
                    BSS_CTGLR, /* the combo, e.g. "11R" */
                    BSS_QLEN, 
                    BSS_QSTART, 
                    BSS_QEND, 
                    BSS_TLEN,
                    BSS_TSTART, 
                    BSS_TEND, 
                    BSS_HITLEN,
                    BSS_MARKER,
                    BSS_RC,
                    BSS_CLONE,
                    BSS_SCORE,
                    BSS_EVALUE,
                    BSS_IDENTITY, 
                    BSS_MATCH, 
                    BSS_INTRON, 
                    BSS_SEQ, 
                  /*  The last two fields are hidden in displays. Don't add any fields
                    after this point, unless you want them hidden also, in which case
                    adjust the BSS_HIDDEN_FIELDS appropriately */
                    BSS_QUERY,   
                    BSS_TARGET,   
                    BSS_MAXFIELD
                } BSS_TYPE;
#define BSS_HIDDEN_FIELDS 0   /* no fields hidden now */
extern char bss_col_widths[BSS_NUMTYPES];
extern char bss_col_widths_px[BSS_NUMTYPES];
extern char bss_mandatory_cols[BSS_NUMTYPES];
int bss_columns_checked[BSS_NUMTYPES]; // one more global array...for a good cause
extern int bss_ncols;

union bss_data_elt
{
    char* str;
    int i;
};

typedef struct bss_hit
{
    union bss_data_elt data[BSS_NUMTYPES];
    int order;
    int filtered;
    struct bss_hit* next; 
} BSS_HIT;

extern void write_bss_file(struct bss_instance* bsi,int);
extern int read_bss_file(char* path, struct bss_instance* pbsi);

extern char cutoff_str[];
extern char xtraParm[];
extern GArray* g_dbs;

/* make sure the size value is bigger than the biggest bss_col_widths value */
#define BSS_FIELD_MAXSIZE 50
#define BSS_FIELD_MAXNUM 30
extern enum  bss_datatype bss_column_order[BSS_NUMTYPES];
extern char bss_fields[BSS_FIELD_MAXNUM][BSS_FIELD_MAXSIZE+1];
extern char bss_headers[BSS_NUMTYPES][BSS_FIELD_MAXSIZE+1];
extern int bss_columns_checked[BSS_NUMTYPES];

extern void safe_strncpy(char* dest, char* src, size_t num);
extern void destroy_bss_instance(struct bss_instance* pbsi);
extern void bss_format_field(char* field,BSS_HIT* hit, BSS_TYPE type);
extern void bss_sort_ctgsec(int col, int factor, struct bss_instance*);
extern void bss_sort_querysec(int col, int factor, struct bss_instance*);
extern void bss_sort_hitlist(BSS_TYPE field,int factor, struct bss_instance*);
extern struct ctgsHitlistType* find_ctg_hit(int ctg, struct ctgsHitlistType *list);
extern void add_to_ctgsHitlist(int ctg, struct ctgsHitlistType **plist);
int collect_fasta_seq_data(char* path, FPC_TREE* ptree,struct bss_instance*,int);
void parse_blast_output(struct bss_instance* pbsi, char* blastfile, FPC_TREE* pqtree, FPC_TREE* pdbtree);
void parse_blat_output(struct bss_instance* pbsi, char* blastfile, FPC_TREE* pqtree, FPC_TREE* pdbtree);
int match_seqclone_to_clone(char* query, int* pcidx);
int match_bes_to_clone(char* query, int* pcidx, struct bss_instance* pbsi);
int parse_seqctg(char* in, char* seqname, int* pctg);
void compute_ctg_query_tables(struct bss_instance* pbsi,int istart, int iend);
void delete_query_hit_data(void** ppdata);
int bss_hit_is_filtered(BSS_HIT* phit);
void output_column_headers(FILE* f);
int bss_is_rc(const BSS_HIT* hit);
void set_column_order(struct bss_instance* bsi);
int check_in_ctg2(int c, int* ctg, char** clonename, char* LR);
void fpc_exec(char* cmd);

#endif /*INC_bss_H*/
